package com.tmt.helper;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期工具
 * Created by Stark on 2017/4/16.
 */
//TODO: 以后将包含 java8 的新的日期格式
public class DateHelper {

    private static final String STR_COLON = ":";
    private static final String STR_SLASH = "/";
    private static final String STR_T = "T";
    private static final String STR_LINE = "-";
    private static final String STR_SPACE = " ";
    private static final String STR_PLUS = "+";

    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_TIME_MILLI_FORMAT = "yyyy-MM-dd HH:mm:ss:SSS";

    public static final String DATE_FORMAT_SLASH = "yyyy/MM/dd";
    public static final String DATE_TIME_FORMAT_SLASH = "yyyy/MM/dd HH:mm:ss";
    public static final String DATE_TIME_MILLI_FORMAT_SLASH = "yyyy/MM/dd HH:mm:ss:SSS";

    public static final String SIMPLE_DATE_FORMAT = "yyyyMMdd";
    public static final String SIMPLE_DATE_TIME_FORMAT = "yyyyMMddHHmmss";
    public static final String SIMPLE_DATE_TIME_MILLI_FORMAT = "yyyyMMddHHmmssSSS";

    public static final String ISO_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
    public static final String ISO_DATE_TIME_MILLI_FORMAT = "yyyy-MM-dd'T'HH:mm:ss:SSS";
    public static final String ISO_DATE_TIME_MILLI_ZONE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss:SSSZ";

    /**
     * 字符转日期，依据不同长度和风格自动转换为日期
     *
     * @param str 待转换的格式
     * @return 日期
     */
    public static Date parseDate(String str) {
        if (StringHelper.isEmpty(str)) {
            return null;
        }

        // 判断顺序，限制条件越多的放前面，尤其是包含字符多的优先级越高
        String format = DATE_TIME_FORMAT;

        if (str.length() == (ISO_DATE_TIME_MILLI_FORMAT.length() - 2) && StringHelper.containsAll(str, Arrays.asList(STR_T, STR_LINE, STR_COLON))) {
            format = ISO_DATE_TIME_MILLI_FORMAT;
        } else if (str.length() == (ISO_DATE_TIME_FORMAT.length() - 2) && StringHelper.containsAll(str, Arrays.asList(STR_T, STR_LINE, STR_COLON))) {
            format = ISO_DATE_TIME_FORMAT;
        } else if (StringHelper.containsAll(str, Arrays.asList(STR_T, STR_LINE, STR_COLON, STR_PLUS))) {
            format = ISO_DATE_TIME_MILLI_ZONE_FORMAT;
        }

        if (str.length() == DATE_TIME_MILLI_FORMAT_SLASH.length() && StringHelper.containsAll(str, Arrays.asList(STR_SLASH, STR_COLON, STR_SPACE))) {
            format = DATE_TIME_MILLI_FORMAT_SLASH;
        } else if (str.length() == DATE_TIME_FORMAT_SLASH.length() && StringHelper.containsAll(str, Arrays.asList(STR_SLASH, STR_COLON, STR_SPACE))) {
            format = DATE_TIME_FORMAT_SLASH;
        } else if (str.length() == DATE_FORMAT_SLASH.length() && StringHelper.containsAll(str, Arrays.asList(STR_SLASH))) {
            format = DATE_FORMAT_SLASH;
        }

        if (str.length() == DATE_TIME_MILLI_FORMAT.length() && StringHelper.containsAll(str, Arrays.asList(STR_LINE, STR_COLON, STR_SPACE))) {
            format = DATE_TIME_MILLI_FORMAT;
        } else if (str.length() == DATE_TIME_FORMAT.length() && StringHelper.containsAll(str, Arrays.asList(STR_LINE, STR_COLON, STR_SPACE))) {
            format = DATE_TIME_FORMAT;
        } else if (str.length() == DATE_FORMAT.length() && StringHelper.containsAll(str, Arrays.asList(STR_LINE))) {
            format = DATE_FORMAT;
        }

        if (str.length() == SIMPLE_DATE_FORMAT.length()) {
            format = SIMPLE_DATE_FORMAT;
        } else if (str.length() == SIMPLE_DATE_TIME_FORMAT.length()) {
            format = SIMPLE_DATE_TIME_FORMAT;
        } else if (str.length() == SIMPLE_DATE_TIME_MILLI_FORMAT.length()) {
            format = SIMPLE_DATE_TIME_MILLI_FORMAT;
        }

        if (str.length() > 0 && str.length() < format.length()) {
            format = format.substring(0, str.length());
        }

        return parseDate(str, format);
    }

    /**
     * 指定格式转换字符串为日期
     *
     * @param str    字符
     * @param format 日期格式
     * @return 最终转换为的日期，可为 null
     */
    public static Date parseDate(String str, String format) {
        DateFormat df = new SimpleDateFormat(format);
        Date result = null;
        try {
            result = df.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 将日期格式化为指定格式字符串
     *
     * @param date   日期对象
     * @param format 日期格式
     * @return 格式化后的字符串
     */
    public static String formatDate(Date date, String format) {
        if (date == null || StringHelper.isEmpty(format)) {
            return "";
        }

        DateFormat df = new SimpleDateFormat(format);
        return df.format(date);
    }

    public static boolean onlyDate(String str) {
        SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
        df.setLenient(false);
        boolean onlyDate = false;

        if (DATE_FORMAT.length() == str.length()) {
            try {
                df.parse(str);
                onlyDate = true;
            } catch (ParseException ignored) {
            }
        }

        if (SIMPLE_DATE_FORMAT.length() == str.length() && !onlyDate) {
            df.applyPattern(SIMPLE_DATE_FORMAT);
            try {
                df.parse(str);
                onlyDate = true;
            } catch (ParseException ignored) {
            }
        }

        if (DATE_FORMAT_SLASH.length() == str.length() && !onlyDate) {
            df.applyPattern(DATE_FORMAT_SLASH);
            try {
                df.parse(str);
                onlyDate = true;
            } catch (ParseException ignored) {
            }
        }
        return onlyDate;
    }

    /**
     * 获取传入日期的最后一时刻
     *
     * @param date 传入时间
     * @return 当天的最后时刻
     */
    public static Date endOfDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));

        return cal.getTime();
    }

    public static Date addMilliSeconds(Date srcDate, int milliSeconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(srcDate);
        calendar.add(Calendar.MILLISECOND, milliSeconds);
        return calendar.getTime();
    }

    public static Date addSeconds(Date srcDate, int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(srcDate);
        calendar.add(Calendar.SECOND, seconds);
        return calendar.getTime();
    }

    public static Date addMinutes(Date srcDate, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(srcDate);
        calendar.add(Calendar.MINUTE, minutes);
        return calendar.getTime();
    }

    public static Date addHours(Date srcDate, int hours) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(srcDate);
        calendar.add(Calendar.HOUR, hours);
        return calendar.getTime();
    }

    public static Date addDays(Date srcDate, int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(srcDate);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return calendar.getTime();
    }

    public static Date addWeeks(Date srcDate, int weeks) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(srcDate);
        calendar.add(Calendar.WEEK_OF_YEAR, weeks);
        return calendar.getTime();
    }

    public static Date addMonths(Date srcDate, int months) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(srcDate);
        calendar.add(Calendar.MONTH, months);
        return calendar.getTime();
    }

    public static Date addYears(Date srcDate, int years) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(srcDate);
        calendar.add(Calendar.YEAR, years);
        return calendar.getTime();
    }


    public static Date getFirstDayOfMonth(int monthOffset) {
        try {
            //获取当前月第一天：
            Calendar c = Calendar.getInstance();
            c.add(Calendar.MONTH, monthOffset);
            //设置为1号,当前日期既为本月第一天
            c.set(Calendar.DAY_OF_MONTH, 1);

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String firstDay = sdf.format(c.getTime());
            return sdf.parse(firstDay);
        } catch (Exception ignored) {
        }
        return null;
    }

    /**
     * 判断两个时间段是否相交
     *
     * @param array1
     * @param array2
     * @return
     */
    public static boolean isIntersect(Date[] array1, Date[] array2) {
        return array1[0].compareTo(array2[0]) >= 0 && array1[1].compareTo(array2[0]) <= 0
                || array1[0].compareTo(array2[1]) >= 0 && array1[1].compareTo(array2[1]) <= 0
                || array2[0].compareTo(array1[0]) >= 0 && array2[1].compareTo(array1[0]) <= 0
                || array2[0].compareTo(array1[1]) >= 0 && array2[1].compareTo(array1[1]) <= 0;
    }


    public static void main(String[] args) {
        getFirstDayOfMonth(0);
        Date date = addDays(new Date(), -5);
        System.out.println(DateHelper.formatDate(date, DateHelper.DATE_TIME_FORMAT));
    }


}
